import asyncio
import concurrent.futures
import os
import threading
import time

loop = asyncio.get_event_loop()

def add2(x):
    print(x+2)
    return x+2

async def add3(x):
    print("in async fun add")
    return x+3

# result = loop.run_until_complete(add3(2))
# print(result)

# async def main():
#     result = await add3(2)
#     return result

async def stesta(x):
    print("in test a")
    await asyncio.sleep(3)
    print(1/0)
    print("Resuming a")
    return x

async def stestb(x):
    print("in test b")
    await asyncio.sleep(1)
    print(1/0)
    print("Resuming b")
    return x

# async def main():
#     start = time.time()
#     resulta = await stesta(1)
#     resultb = await stestb(2)
#     print("test a result is %d" % resulta)
#     print("test b result is %d" % resultb)
#     print("use %s time" % (time.time() - start))

# async def main():
#     start = time.time()
#     resulta, resultb = await asyncio.gather(stesta(1), stestb(2))
#     print("test a result is %d" % resulta)
#     print("test b result is %d" % resultb)
#     print("use %s time" % (time.time() - start))

# async def main():
#     start = time.time()
#     taska = asyncio.ensure_future(stesta(1))
#     taskb = asyncio.ensure_future(stestb(2))
#     print(taska)
#     print(taskb)
#     print("*" * 30)
#     print(taska.done(), taskb.done())
#     print("=" * 30)
#     await taska
#     await taskb
#     print(taska.done(), taskb.done())
#     print("=" * 30)
#     print(taskb.result())
#     print(taska.result())
#     print("use  %s time" % (time.time() - start))


# async def main():
#     start = time.time()
#     taska = loop.create_task(stesta(1))
#     taskb = loop.create_task(stestb(2))
#     print(taska)
#     print(taskb)
#     print(taska.done(), taskb.done())
#     await taska
#     await taskb
#     print(taska.done(), taskb.done())
#     print(taskb.result())
#     print(taska.result())
#     print("use %s time" % (time.time() - start))

# wait和gather有哪些区别
# gather是需要所有任务都执行结束，如果某一个协程函数崩溃了，则会抛异常 ，都不会有结果
# wait 可以定义函数返回的时机，可以是first_completed(第一个结束的),first_exception(第一个出现异常的),all_completed(全部执行完，默认的)
# async def main():
#     start = time.time()
#     done, pending = await asyncio.wait([stesta(1), stestb(2)], return_when=asyncio.tasks.FIRST_EXCEPTION)
#     print(list(done))
#     print(list(pending))
#     print("use %s time" % (time.time() - start))

# if __name__ == "__main__":
#     loop = asyncio.get_event_loop()
#     loop.run_until_complete(main())


def ping(url):
    print("阻塞函数开始运行,当前的线程ID为：",threading.current_thread(),"进程ID为：",os.getpid())
    time.sleep(2)
    os.system("ping %s" % url)
    print("阻塞函数运行结束,当前的线程ID为：",threading.current_thread())

async def asyncfunc1():
    print("Suspending func1")
    await asyncio.sleep(1)
    print("func func1 ", threading.current_thread())
    print("Resuming func1")
    return "func1"

async def asyncfunc2():
    print("Suspending func2")
    await asyncio.sleep(1)
    print("func func2 ", threading.current_thread())
    print("Resuming func2")
    return "func2"

def callbackfunc(task):
    print("task 运行结束，它的结果是：",task.result())
    # 执行loop.run_forever()时，执行以下方法
    # loop.stop()


async def main():
    task1 = loop.create_task(asyncfunc1())
    task1.add_done_callback(callbackfunc)
    task2 = loop.create_task(asyncfunc2())
    task2.add_done_callback(callbackfunc)
    result = await asyncio.gather(task1, task2)
    print(result)

async def main2():
    result = await asyncio.gather(asyncfunc1(), asyncfunc2())
    print(result)

def start_thread_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

if __name__ == "__main__":
    print("In main thread ", threading.current_thread())
    # loop = asyncio.get_event_loop()
    # task = loop.create_task(asyncfunc1())
    # task.add_done_callback(callbackfunc)
    # loop.run_until_complete(task)
    # print("task result is ", task.result())

    # time.sleep(3)

    # task = loop.create_task(asyncfunc1())
    # task.add_done_callback(callbackfunc)
    # loop.run_forever()

    # task1 = loop.create_task(asyncfunc1())
    # task1.add_done_callback(callbackfunc)
    # task2 = loop.create_task(asyncfunc2())
    # task2.add_done_callback(callbackfunc)
    # loop.run_forever()


    # loop = asyncio.get_event_loop()
    # loop.run_until_complete(main())

    # t1 = threading.Thread(target=ping, args=("www.baidu.com",))
    # t2 = threading.Thread(target=ping, args=("www.sina.com",))
    # t3 = threading.Thread(target=ping, args=("www.qq.com",))
    # t1.start()
    # t2.start()
    # t3.start()

    # # 在子线程中运行事件循环，让它run_forever
    # loop = asyncio.get_event_loop()
    # t = threading.Thread(target=start_thread_loop, args=(loop,))
    # t.start()
    #
    # # 在主线程中动态添加同步函数
    # loop.call_soon_threadsafe(ping, "www.baidu.com")
    # loop.call_soon_threadsafe(ping, "www.qq.com")
    # loop.call_soon_threadsafe(ping, "www.sina.com")
    # print("主线程不会阻塞")

    loop = asyncio.get_event_loop()
    t = threading.Thread(target=start_thread_loop, args=(loop,))
    t.start()
    threadingexecutor = concurrent.futures.ThreadPoolExecutor(2)
    processExecutor = concurrent.futures.ProcessPoolExecutor()

    loop.run_in_executor(processExecutor, ping, "www.baidu.com")
    loop.run_in_executor(processExecutor, ping, "www.qq.com")
    loop.run_in_executor(processExecutor, ping, "www.sina.com")
    print("主线程不会阻塞")


